P04-1. Zero-Trust 보안과 SPIFFE SVID 인증 인가 - 이론 개념

Part 04 (이론): Zero-Trust 보안과 SPIFFE/SVID 인증 · 인가

핵심 학습 목표

  1. 전통적인 성벽형 보안(경계 보안)이 쿠버네티스 환경에서 왜 무력화되는지(측면 이동 공격과 파드 IP의 휘발성), 그리고 Zero-Trust(제로 트러스트) 가 이를 어떻게 해결하는지 설명할 수 있다.
  2. IP 주소 대신 파드의 신분을 증명하는 CNCF 표준 규격인 SPIFFE ID(spiffe://cluster.local/ns/.../sa/...) 와 SVID(X.509 인증서 SAN 확장 필드) 의 구조를 해부한다.
  3. 인증(PeerAuthentication: PERMISSIVE vs STRICT) 과 인가(AuthorizationPolicy: DENY vs ALLOW 우선순위) 의 차이를 명확히 구분한다.
  4. Ambient Mesh에서 L4 인가 정책은 왜 ztunnel이 집행하고, L7 인가 정책(GET/DELETE, URL 경로)은 왜 반드시 Waypoint Proxy가 집행해야 하는지 아키텍처 수준에서 이해한다.


1. 왜 쿠버네티스에서는 IP 방화벽이 소용없을까? (Zero-Trust의 탄생)

과거 온프레미스 서버나 전통적인 VM 환경에서는 "성벽과 해자(Castle-and-Moat)" 모델, 즉 경계 기반 보안(Perimeter Security) 을 사용했습니다.
회사 데이터센터 정문에 비싼 방화벽 하나를 튼튼하게 세워 두고, 일단 그 정문을 통과해 내부망(사설 IP 대역)에 들어온 서버들끼리는 서로를 100% 믿고 평문(HTTP)으로 자유롭게 통신하게 두었습니다. 또한 방화벽 규칙도 "웹 서버(192.168.1.10)에서 DB 서버(192.168.2.50)의 5432 포트로 가는 것만 허용해라" 처럼 고정된 IP 주소를 기준으로 짰습니다.

하지만 클라우드 네이티브(쿠버네티스) 환경에서는 이 두 가지 가정이 완전히 깨집니다.

  1. 측면 이동 공격 (Lateral Movement):
    쿠버네티스의 기본 네트워크(CNI)는 클러스터 안의 모든 파드가 서로 통신할 수 있는 평평한 네트워크(Flat Network)입니다. 만약 해커가 외부에 노출된 덜 중요한 이벤트 페이지 파드 하나를 해킹해 들어오면, 내부망에서는 아무런 신분 검사를 하지 않기 때문에 그 파드를 발판 삼아 옆에 있는 결제 API 파드나 고객 DB까지 아무 제지 없이 옮겨 다닐 수 있습니다.
  2. 파드 IP의 휘발성 (Ephemeral Pod IP):
    쿠버네티스에서 파드는 오토스케일링이나 배포 때마다 하루에도 수십 번씩 죽고 새로 태어나며, 그때마다 IP 주소(10.244.x.x)가 계속 바뀝니다. 심지어 1분 전까지 결제 파드가 쓰던 10.244.1.5 IP를, 결제 파드가 죽자마자 엉뚱한 프론트엔드 파드가 물려받아 쓸 수도 있습니다. 즉, 쿠버네티스에서 "IP 주소 = 서버의 신분"이라는 공식은 성립하지 않습니다.

이 한계를 극복하기 위해 등장한 현대 보안의 대원칙이 바로 Zero-Trust(제로 트러스트) 입니다.

용어 정리 — Zero-Trust Architecture (제로 트러스트 보안)

  • 핵심 슬로건: "Never Trust, Always Verify (절대 믿지 말고, 매번 검증하라)"
  • 개념: 패킷이 우리 회사 내부망(같은 클러스터, 심지어 같은 워커 노드) 안에서 날아왔다는 이유만으로 절대 신뢰하지 않습니다. 모든 파드 간 요청(동서 트래픽)마다 다음 세 가지를 강제합니다:
    1. 모든 통신의 암호화 (mTLS): 내부망 도청 원천 차단
    2. 암호학적 신원 확인 (Authentication, 인증): IP가 아니라 위조 불가능한 전자 여권(SPIFFE)으로 "너는 정말 누구냐?" 를 확인
    3. 최소 권한 부여 (Authorization, 인가): 신원이 확인되었더라도 "너에게 이 API 경로를 호출할 권한이 있는가?" 를 매 요청마다 심사


2. IP를 대체하는 파드의 전자 여권: SPIFFE 와 SVID

IP 주소를 믿을 수 없다면, ztunnel과 Waypoint는 도대체 무엇을 보고 상대방 파드의 신분을 확인할까요?
바로 쿠버네티스의 ServiceAccount(서비스 어카운트) 와 연동된 국제 표준 신분증 규격인 SPIFFE 입니다!

flowchart LR
    subgraph K8S["1. K8s 리소스 정의"]
        SA["ServiceAccount: order-sa
Namespace: part1-demo"] --> POD["order-api 파드 실행
(spec.serviceAccountName: order-sa)"] end subgraph ISTIOD["2. istiod (CA 인증기관)"] CA["내장 인증기관 (Citadel)
X.509 전자 인증서(SVID) 서명·발급"] end subgraph CERT["3. 발급된 SVID 인증서 내부 (X.509 SAN 필드)"] URI["URI: spiffe://cluster.local/ns/part1-demo/sa/order-sa
유효기간: 24시간 (자동 갱신)"] end POD -->|"파드 생성/노드 배치"| CA -->|"SDS 보안 채널로 ztunnel에 전달"| CERT
용어 정리 — ServiceAccount, SPIFFE, SVID, X.509 SAN

  1. ServiceAccount (서비스 어카운트):
    • 쿠버네티스에서 '사람(개발자)'이 쓰는 계정이 아니라, '파드(프로그램)'에게 부여하는 전용 계정(명찰) 입니다. 파드를 만들 때 따로 지정하지 않으면 그 네임스페이스의 기본 계정인 default ServiceAccount가 자동으로 붙지만, 실무 보안에서는 마이크로서비스마다 전용 계정(order-sa, payment-sa 등)을 만들어 붙여 줍니다.
  2. SPIFFE (Secure Production Identity Framework for Everyone, 스피피):
    • 파드나 VM의 IP 주소가 바뀌더라도 변하지 않는 전 세계 표준 워크로드 주민등록번호 체계(CNCF 졸업 프로젝트)입니다.
    • 형식은 항상 다음과 같은 URI 구조를 가집니다:
      spiffe://<신뢰도메인(Trust Domain)>/ns/<네임스페이스>/sa/<서비스어카운트>
      (예: spiffe://cluster.local/ns/part1-demo/sa/order-sa)
  3. SVID (SPIFFE Verifiable Identity Document):
    • 위 SPIFFE 주민등록번호를 istiod 본부(인증기관, CA)가 위조 불가능한 X.509 디지털 인증서 안에 도장을 찍어 발급해 준 실물 전자 여권입니다.
  4. X.509 SAN (Subject Alternative Name, 주체 대체 이름):
    • 디지털 인증서 안에서 소유자의 신분(spiffe://... URI나 도메인 이름)을 적어 넣는 표준 확장 칸입니다. ztunnel끼리 HBONE(:15008) 터널을 맺을 때 서로의 인증서 속 SAN 칸에 적힌 spiffe://... 문자열을 꺼내어 상대방이 누구인지 100% 암호학적으로 검증합니다.


3. 1단계 관문 — 인증 (Authentication: 너는 누구냐?)

보안 검문은 항상 1단계 인증(Authentication, 줄여서 AuthN) 과 2단계 인가(Authorization, 줄여서 AuthZ) 순서로 진행됩니다.
공항 출입국 심사대에 비유하면 이해가 아주 쉽습니다.

Istio에서 1단계인 파드 간 mTLS 인증 강도를 조절하는 쿠버네티스 리소스가 바로 PeerAuthentication 입니다.

PeerAuthentication 모드 동작 방식 (공항 비유) 언제 사용하나요?
PERMISSIVE (기본값, 허용 모드) 상대방이 암호화된 터널(mTLS / HBONE)로 오면 신분증을 검사해 받고, 아직 메시에 들어오지 않은 레거시 파드가 평문(Plaintext TCP)으로 요청해도 일단 문은 열어 줌 기존 운영 중인 클러스터에 서비스 메시를 처음 도입하며 파드들을 순차적으로 메시에 편입(마이그레이션)할 때
STRICT (엄격 모드, Zero-Trust 표준) 무조건 유효한 SPIFFE 신분증으로 암호화된 mTLS(HBONE) 통신만 허용! 신분증이 없는 평문 접근은 그 즉시 연결 거부 모든 워크로드가 메시에 편입된 후, 내부망 도청과 미인증 파드의 접근을 100% 차단할 때

4. 2단계 관문 — 인가 (Authorization: 무엇을 할 자격이 있느냐?)

여권 심사(PeerAuthentication)를 통과해 상대방의 정확한 신분(spiffe://cluster.local/ns/part1-demo/sa/study-client-sa)이 확인되었다면, 이제 AuthorizationPolicy 리소스로 정교한 출입 통제 규칙을 적용합니다.

4-1. AuthorizationPolicy 평가 우선순위 (반드시 알아야 할 황금 규칙!)

한 네임스페이스나 서비스에 여러 개의 AuthorizationPolicy가 걸려 있을 때, Istio는 아래 순서대로 심사합니다.

flowchart LR
    REQ["패킷 도착
(신분: spiffe://.../sa/client)"] --> STEP1{"1. DENY(거부) 정책에
하나라도 걸리는가?"} STEP1 -->|"예 (매칭됨)"| BLOCK1["즉시 차단!
(Deny Wins)"] STEP1 -->|"아니오"| STEP2{"2. 등록된 ALLOW(허용)
정책이 존재하는가?"} STEP2 -->|"아예 없음 (0개)"| PASS1["통과 허용
(기본 개방 상태)"] STEP2 -->|"1개 이상 있음"| STEP3{"3. ALLOW 정책 조건에
정확히 일치하는가?"} STEP3 -->|"예 (매칭됨)"| PASS2["통과 허용!"] STEP3 -->|"아니오 (명단에 없음)"| BLOCK2["즉시 차단!
(화이트리스트 모드 작동)"]
실무에서 가장 많이 놀라는 포인트: ALLOW 정책을 단 1개라도 만드는 순간 화이트리스트(Default Deny)가 됩니다!

  • 아무런 AuthorizationPolicy가 없을 때는 모든 파드의 통신이 허용됩니다.
  • 하지만 특정 서비스에 action: ALLOW 정책을 단 1개라도 등록하는 순간, 그 정책에 적히지 않은 나머지 모든 접근은 자동으로 전면 차단(Default Deny) 됩니다! 즉, "A에게만 허용한다 = A가 아닌 나머지는 전부 막는다" 는 뜻으로 동작하므로 보안 사고를 막는 데 매우 강력합니다.

4-2. Ambient Mesh의 핵심 설계: L4 인가(ztunnel) vs L7 인가(Waypoint)

Part 03에서 배웠듯 Ambient Mesh는 데이터 플레인을 노드 레벨 L4 프록시(ztunnel) 와 네임스페이스/서비스 레벨 L7 프록시(Waypoint) 로 철저히 분리했습니다.
따라서 우리가 작성하는 AuthorizationPolicy도 안에서 어떤 조건을 검사하느냐에 따라 집행관이 달라집니다!

구분 L4 인가 정책 (ztunnel 단독 집행) L7 인가 정책 (Waypoint Proxy 필수!)
검사 가능한 조건 출발지 신분(principals / ServiceAccount), 출발지 네임스페이스(namespaces), 출발지 IP(ipBlocks), 목적지 포트(ports) 위 L4 조건 전체 + HTTP 메서드(GET, POST, DELETE), URL 경로(paths: ["/admin*"]), HTTP 헤더(headers), 도메인(hosts)
누가 검문하나요? 서버 노드의 ztunnel (Rust L4 프록시) 네임스페이스/서비스의 Waypoint Proxy (Envoy L7 프록시)
차단 시 클라이언트가 보는 현상 TCP 연결 자체가 즉시 끊김 (curl: (56) Recv failure: Connection reset by peer 또는 빈 응답) 정식 HTTP 상태 코드 403 Forbidden 과 본문 RBAC: access denied 반환
만약 Waypoint 없이 ztunnel만 있는 상태에서 L7 규칙(methods: ["GET"])을 넣으면? ztunnel은 보안상 HTTP 본문을 뜯어보지 않으므로 "어? 이 정책에는 내가 읽을 수 없는 L7 조건이 들어있네? 잘못 열었다가 보안 사고가 나느니 아예 전면 차단(Fail-Close)하자!" 라며 트래픽을 막아버립니다! 따라서 HTTP 메서드나 URL 경로 기반 정책을 쓸 때는 반드시 Waypoint Proxy 를 함께 배포해야 합니다.

🔗 다음 단계 (실습 검증)

이론으로 배운 Zero-Trust 보안의 모든 요소를 이제 우리의 docker-desktop 클러스터에서 직접 검증해 봅니다!

  1. ztunnel이 메모리에 들고 있는 실제 SPIFFE X.509 인증서를 꺼내어 SAN 필드에 적힌 spiffe://cluster.local/... 신분증을 눈으로 확인하고,
  2. PeerAuthentication (STRICT) 와 AuthorizationPolicy 를 이용해 허가받은 ServiceAccount만 접근을 허용하고,
  3. Waypoint Proxy 를 통해 GET /headers 요청은 200 OK로 통과시키되 DELETE 요청이나 /admin 경로 접근은 403 RBAC: access denied로 칼같이 차단하는 실습을 진행합니다.

네비게이션

이전 목록 다음
◀ Part 03 실습 목록으로 Part 04 실습 ▶